package me.xlgp.xiquzimu.data;

import java.util.List;
import java.util.NoSuchElementException;

import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.functions.Function;
import me.xlgp.xiquzimu.designpatterns.ObserverHelper;
import me.xlgp.xiquzimu.model.ChangCi;
import me.xlgp.xiquzimu.model.ChangDuan;
import me.xlgp.xiquzimu.model.ChangDuanInfo;
import me.xlgp.xiquzimu.model.ZiMuInfo;
import me.xlgp.xiquzimu.util.ChangDuanHelper;

public class ChangDuanInfoRepository {

    private ChangDuanInfo get(Integer changDuanId) {
        ChangCiRepository changCiRepository = new ChangCiRepository();
        ChangDuanRepository changDuanRepository = new ChangDuanRepository();

        ChangDuan changDuan = changDuanRepository.get(changDuanId);
        if (changDuan == null) {
            throw new NoSuchElementException("无法查询唱段");
        }

        List<ChangCi> changCiList = changCiRepository.listByChangDuanId(changDuanId);
        if (changCiList == null || changCiList.isEmpty()) {
            throw new NoSuchElementException("无法查询唱词");
        }

        ChangDuanInfo changDuanInfo = new ChangDuanInfo();
        changDuanInfo.setChangDuan(changDuan);
        changDuanInfo.setChangCiList(changCiList);
        return changDuanInfo;
    }

    public Observable<ZiMuInfo> getZiMuInfo(Integer changDuanId) {
        return Observable.create((ObservableOnSubscribe<ZiMuInfo>) emitter -> {
            ZiMuInfo ziMuInfo = new ZiMuInfo();
            ChangDuanInfo changDuanInfo = get(changDuanId);
            ziMuInfo.setChangDuan(changDuanInfo.getChangDuan());
            ziMuInfo.setChangCiList(ChangDuanHelper.parseChangCiList(ziMuInfo.getChangDuan(), changDuanInfo.getChangCiList()));
            emitter.onNext(ziMuInfo);
        }).compose(ObserverHelper.transformer());
    }

    //在本地操作后，保存唱段到本地数据库
    public @NonNull Observable<Object> save(ChangDuanInfo changDuanInfo) {
        ChangDuanRepository changDuanRepository = new ChangDuanRepository();
        return changDuanRepository.update(changDuanInfo);
    }

    public Observable<ChangDuanInfo> getChangDuanInfo(Integer id) {
        return Observable.create((ObservableOnSubscribe<ChangDuanInfo>) emitter -> emitter.onNext(get(id))).compose(ObserverHelper.transformer());
    }

    //从远程获取唱段数据，并保存到本地数据库
    public Observable<Long> fetchChangDuanList() {
        ChangDuanRepository changDuanRepository = new ChangDuanRepository();
        FetchRemoteRepository fetchRemoteRepository = new FetchRemoteRepository();
        return changDuanRepository.getNameList()
                .flatMap((Function<me.xlgp.xiquzimu.responsebody.ChangDuanInfo, ObservableSource<String>>) changDuanInfo -> {
                    if (changDuanInfo.getNameList().size() == 0)
                        throw new NoSuchElementException("没有远程数据");
                    //保存剧种
                    new JuZhongRepository().save(changDuanInfo.getJuZhongList());
                    return Observable.fromIterable(changDuanInfo.getNameList());
                }).flatMap((Function<String, ObservableSource<List<String>>>) fetchRemoteRepository::changDuan)
                .flatMap((Function<List<String>, ObservableSource<Long>>) list -> changDuanRepository.saveAynsc(ChangDuanHelper.parse(list)))
                .compose(ObserverHelper.transformer());
    }
}
